Imports System.Drawing.Drawing2D
Imports DevExpress.XtraTreeList.Columns
Imports DevExpress.XtraTreeList.Nodes
Imports MindFusion.Diagramming

Public Class UcnGridUnbound
    'represents unbound grid

#Region "Attributes"
#Region "Private attributes"
    Private MbReadyForUse As Boolean = False 'indicates proper creation or first initialization of usercontrol
    Private MoItem As Object = Nothing  'actual selected item
    Private MoOldCellValue As Object = Nothing 'old cell value after value was changed to new value
    Private MoImplicitBaseEditor As DevExpress.XtraEditors.BaseEdit = Nothing 'implicit editor for editing cells - used for immediate accepting changes after click on base editor of cell
    Private MoTag As Object = Nothing 'tag for free use
#End Region
#End Region
#Region "Events"
    Public Event MMSettings() 'event is raised for setting this control settings
    Public Event MMCreateDataSource() 'event is raised for creating datasource for TreeList
    Public Event MMColumnProperties(ByRef Column As TreeListColumn) 'event is raised for setting properties of column - visibility, ability to edit, header caption etc
    Public Event MMFillDataSource(ByVal Item As Object, ByRef DataSource As Collection) 'event is raised for filling datasource
    Public Event MMCustomDrawNodeCell(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs) 'event is raised for setting properties of cell while it is drawing
    Public Event MMCustomNodeCellEdit(ByVal e As DevExpress.XtraTreeList.GetCustomNodeCellEditEventArgs) 'event is raised for assignment an editor to cell
    Public Event MMShowingEditor(ByVal e As System.ComponentModel.CancelEventArgs) 'event is raised before activating an cell editor
    Public Event MMValueValidating(ByVal Item As Object, ByVal Row As TreeListNode, ByVal Column As TreeListColumn, ByRef Value As Object, ByRef Valid As Boolean, ByRef ErrorText As String) 'event is raised while validating new value
    Public Event MMInvalidValueException(ByVal e As DevExpress.XtraEditors.Controls.InvalidValueExceptionEventArgs) 'event is raised after invalid cell value was entered
    Public Event MMValueChanged(ByVal Row As TreeListNode, ByVal Column As TreeListColumn, ByVal NewValue As Object, ByVal OldValue As Object) 'event is raised when value of cell was successfully changed
    Public Event MMBeforeCheckNode(ByVal Row As TreeListNode) 'event is raised before check button of node is checked
    Public Event MMAfterCheckNode(ByVal Row As TreeListNode) 'event is raised after check button of node was checked
    Public Event MMFocusedRowChanged(ByVal NewRow As TreeListNode, ByVal OldRow As TreeListNode) 'event is raised immediately after changing the focused node
    Public Event MMRowDoubleClicked(ByVal Row As TreeListNode) 'event is raised after node was doubleclicked
#End Region
#Region "Constructors & Init"
    Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.


        '**********************************************************************
        InitControl()
        '**********************************************************************
    End Sub
    'setting usercontrol settings before its using
    Private Function InitControl() As GeActionResult
        SetReadyForUse(False) 'disabling usercontrol
        Try
            tlTreeList.DataSource = New Collection

            SetReadyForUse(True) 'enabling usercontrol
            Return GeActionResult.kkOk
        Catch ex As Exception
            LogEventFromException(ex, , , )
            Return GeActionResult.kkError
        End Try
    End Function
    'initialization of controls
    Public Function Init(ByVal IoActualItem As Object) As GeActionResult
        Try
            If MbReadyForUse Then
                MoItem = IoActualItem
                RefreshPropertiesOfItem(IoActualItem)

                Return GeActionResult.kkOk
            Else
                LogEvent("Neinicializovany UcnListBox!", , )
                Return GeActionResult.kkError
            End If
        Catch ex As Exception
            LogEventFromException(ex, , , )
            Return GeActionResult.kkError
        End Try
    End Function
#End Region
#Region "Properties"
#Region "Public properties"
    Public ReadOnly Property ReadyForUse() As Boolean
        Get
            Return MbReadyForUse
        End Get
    End Property
    Public Property MMTag() As Object
        Get
            Return MoTag
        End Get
        Set(ByVal IoValue As Object)
            MoTag = IoValue
        End Set
    End Property
#End Region
#End Region
#Region "Events handler"
#Region "tlPropertiesOfItem - Events handler"
    Private Sub tlTreeList_CustomDrawNodeCell(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.CustomDrawNodeCellEventArgs) Handles tlTreeList.CustomDrawNodeCell
        RaiseEvent MMCustomDrawNodeCell(sender, e)
    End Sub
    'saving old (original) value of cell for later use; addressing sub ImplicitBaseEditorEditValueChanged for immediate accepting changes after click on base editor of cell
    Private Sub tlPropertiesOfItem_ShownEditor(ByVal sender As Object, ByVal e As System.EventArgs) Handles tlTreeList.ShownEditor
        Debug.Print("tlPropertiesOfItem_ShownEditor")
        MoOldCellValue = tlTreeList.ActiveEditor.EditValue()

        'exclude some editors coz I dont want to raise CellValueChanged event during typing text within them
        If tlTreeList.ActiveEditor.GetType.Name <> "TextEdit" And tlTreeList.ActiveEditor.GetType.Name <> "ButtonEdit" Then
            MoImplicitBaseEditor = tlTreeList.ActiveEditor
            AddHandler MoImplicitBaseEditor.EditValueChanged, AddressOf ImplicitBaseEditorEditValueChanged
        End If
    End Sub
    'removing event ImplicitRepository_EditorEditValueChanged
    Private Sub tlPropertiesOfItem_HiddenEditor(ByVal sender As Object, ByVal e As System.EventArgs) Handles tlTreeList.HiddenEditor
        Debug.Print("tlPropertiesOfItem_HiddenEditor")
        If MoImplicitBaseEditor IsNot Nothing Then
            RemoveHandler MoImplicitBaseEditor.EditValueChanged, AddressOf ImplicitBaseEditorEditValueChanged
            MoImplicitBaseEditor = Nothing
        End If
    End Sub
    'changing value of cell
    Private Sub tlPropertiesOfItem_CellValueChanged(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.CellValueChangedEventArgs) Handles tlTreeList.CellValueChanged
        Debug.Print("tlPropertiesOfItem_CellValueChanged" & DateTime.Now)
        'tlPropertiesOfItem.UpdateCurrentRow()
        RaiseEvent MMValueChanged(tlTreeList.FocusedNode, e.Column, e.Value, MoOldCellValue)
    End Sub
    'value validating
    Private Sub tlPropertiesOfItem_ValidatingEditor(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.Controls.BaseContainerValidateEditorEventArgs) Handles tlTreeList.ValidatingEditor
        Debug.Print("tlPropertiesOfItem_ValidatingEditor")
        e.Valid = False
        e.ErrorText = ""

        RaiseEvent MMValueValidating(MoItem, tlTreeList.FocusedNode, tlTreeList.FocusedColumn, e.Value, e.Valid, e.ErrorText)
    End Sub
    'before check button of node is checked
    Private Sub tlTreeList_BeforeCheckNode(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.CheckNodeEventArgs) Handles tlTreeList.BeforeCheckNode
        RaiseEvent MMBeforeCheckNode(e.Node)
    End Sub
    'after check button of node was checked
    Private Sub tlTreeList_AfterCheckNode(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.NodeEventArgs) Handles tlTreeList.AfterCheckNode
        RaiseEvent MMAfterCheckNode(e.Node)
    End Sub
    'response to an invalid cell value
    Private Sub tlTreeList_InvalidValueException(ByVal sender As Object, ByVal e As DevExpress.XtraEditors.Controls.InvalidValueExceptionEventArgs) Handles tlTreeList.InvalidValueException
        RaiseEvent MMInvalidValueException(e)
    End Sub
    'assignment an editor to cell
    Private Sub tlTreeList_CustomNodeCellEdit(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.GetCustomNodeCellEditEventArgs) Handles tlTreeList.CustomNodeCellEdit
        RaiseEvent MMCustomNodeCellEdit(e)
    End Sub
    'before activating an editor
    Private Sub tlTreeList_ShowingEditor(ByVal sender As Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles tlTreeList.ShowingEditor
        RaiseEvent MMShowingEditor(e)
    End Sub
    'immediately after changing the focused node
    Private Sub tlTreeList_FocusedNodeChanged(ByVal sender As Object, ByVal e As DevExpress.XtraTreeList.FocusedNodeChangedEventArgs) Handles tlTreeList.FocusedNodeChanged
        RaiseEvent MMFocusedRowChanged(e.Node, e.OldNode)
    End Sub
    'double click event
    Private Sub tlTreeList_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tlTreeList.DoubleClick
        Dim LoPoint As Point = Control.MousePosition
        LoPoint = tlTreeList.PointToClient(LoPoint)
        Dim LoHinfo As DevExpress.XtraTreeList.TreeListHitInfo = tlTreeList.CalcHitInfo(LoPoint)
        If Not LoHinfo.Node Is Nothing Then
            RaiseEvent MMRowDoubleClicked(LoHinfo.Node)
        End If
    End Sub
#End Region
#End Region
#Region "Functions"
    'refreshing properties of item
    Private Function RefreshPropertiesOfItem(ByVal IoActualItem As Object) As GeActionResult
        Try
            Clear()
            tlTreeList.BeginUpdate()

            MoItem = IoActualItem 'coz in Clear() is MoItem = Nothing
            'settings for this control
            RaiseEvent MMSettings()
            'creating datasource
            CreateDataSource()
            'filling properties of columns
            RefreshColumns()
            'filling data source
            RefreshDataSource(True)

            tlTreeList.EndUpdate()

            Return GeActionResult.kkOk
        Catch ex As Exception
            LogEventFromException(ex, , , )
            Return GeActionResult.kkError
        End Try
    End Function
    Private Function CreateDataSource() As GeActionResult
        Try
            RaiseEvent MMCreateDataSource()

            Return GeActionResult.kkOk
        Catch ex As Exception
            LogEventFromException(ex, , , )
            Return GeActionResult.kkError
        End Try
    End Function
    'refreshing properties of columns
    Private Function RefreshColumns() As GeActionResult
        Try
            For Each LoTreeListColumn As TreeListColumn In tlTreeList.Columns
                'properties of columns
                RaiseEvent MMColumnProperties(LoTreeListColumn)
            Next
            '"RowID" AND "ParentRowID" ARE UNIQUE IDENTIFIERS FOR TREELIST AND THESE COLUMNS ARE INVISIBLE IN TREELIST COZ THEY ARE SET TO PROPERTIES KeyFieldName and ParentFieldName PROPERTIES OF TREELIST

            Return GeActionResult.kkOk
        Catch ex As Exception
            LogEventFromException(ex, , , )
            Return GeActionResult.kkError
        End Try
    End Function
    'refreshing content of grid - data source
    Public Function RefreshDataSource(Optional ByVal IbCallingDuringInit As Boolean = False) As GeActionResult
        Try
            If Not IbCallingDuringInit Then tlTreeList.BeginUpdate()

            tlTreeList.DataSource = New Collection
            'CType(tlTreeList.DataSource, Collection).Clear() 'clearing datasource

            RaiseEvent MMFillDataSource(MoItem, tlTreeList.DataSource)

            'IMPORTANT!!! TO MAKE NODES VISIBLE!!!
            'tlTreeList.BestFitColumns()
            tlTreeList.ExpandAll()
            'IMPORTANT!!! TO MAKE NODES VISIBLE!!!

            If Not IbCallingDuringInit Then tlTreeList.EndUpdate()

            Return GeActionResult.kkOk
        Catch ex As Exception
            LogEventFromException(ex, , , )
            Return GeActionResult.kkError
        End Try
    End Function
#End Region
#Region "Subs"
    'sets MbReadyForUse attribute and sets Enable property of usercontrol
    Private Sub SetReadyForUse(ByVal IbValue As Boolean)
        MbReadyForUse = IbValue
        Me.Enabled = IbValue 'enabling usercontrol
    End Sub
    'sub for immediate accepting a changes made in implicit editor of cell
    Private Sub ImplicitBaseEditorEditValueChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        Debug.Print("ImplicitBaseEditorEditValueChanged")
        tlTreeList.PostEditor()
    End Sub
    'clear datatsource and nodes
    Public Sub Clear()
        Me.tlTreeList.BeginUpdate()

        MoItem = Nothing
        CType(tlTreeList.DataSource, Collection).Clear() 'clearing datasource
        'tlTreeList.DataSource = Nothing  'clearing datasource
        Me.tlTreeList.ClearNodes() 'clearing nodes

        Me.tlTreeList.EndUpdate()
    End Sub
#End Region

End Class
